import Enum from '$enum'
import validator from './validator.js'


let requiredMsg = '必填'
let numberMsg = '必须是数字'

const clone = function (obj, copy) {
    /// <summary>克隆对象</summary>
    /// <param name="obj">需要克隆的对象</param>

    // Handle the 3 simple types, and null or undefined
    if (obj == null || typeof obj !== 'object') return obj

    // Handle Date
    if (obj instanceof Date) {
        copy = copy || new Date()
        copy.setTime(obj.getTime())
        return copy
    }

    // Handle Array
    if (obj instanceof Array) {
        copy = copy || []
        for (var i = 0, len = obj.length; i < len; ++i) {
            copy[i] = clone(obj[i])
        }
        return copy
    }

    // Handle Object
    if (obj instanceof Object) {
        copy = copy || {}
        for (var attr in obj) {
            if (obj.hasOwnProperty(attr)) copy[attr] = clone(obj[attr])
        }
        return copy
    }

    throw new Error("Unable to copy obj! Its type isn't supported.")
}

// 转换选项为数组集合
const convertOptions = function ({
    options,
    props,
    excludeArray,
    objSource
}) {
    /// <summary>转换选项为数组集合</summary>
    let tempOptions = []
    props = props || {
        label: 'label',
        value: 'value'
    }
    excludeArray = excludeArray || []
    objSource = objSource || options

    switch (Object.prototype.toString.call(options)) {
        case '[object Function]': // 函数类型
            tempOptions = options()
            break
        case '[object Object]': // 枚举类型
            for (var key in options) {
                let option = {}

                // option[props.label] = parseEnumKey(key);
                option[props.label] = parseEnumValue({
                    objSource: objSource || options,
                    enumValue: options[key]
                })
                option[props.value] = options[key]
                // option[props.disabled || 'disabled'] = typeof (option[this.myProps.disabled]) == 'boolean' ? option[this.myProps.disabled] : false

                tempOptions.push(option)
            }
            break
        case '[object Array]': // 数组集合类型
            options.forEach((option) => {
                if (excludeArray.indexOf(option[props.label]) == -1) {
                    tempOptions.push(option)
                }
            })

            return tempOptions
            break
        default:
            return this.convertOptions({
                options,
                props,
                excludeArray,
                objSource
            })
            break
    }

    return this.convertOptions({
        options: tempOptions,
        props,
        excludeArray,
        objSource
    })
}

/*
 * 把枚举对象转换为key，value的数据源数组列表对象
 */
const convertEnum = function ({
    objSource,
    includeArray,
    excludeArray,
    key,
    value
}) {
    includeArray = includeArray || {}
    excludeArray = excludeArray || {}
    key = key || 'name'
    value = value || 'value'

    let enumObject = objSource
    if (includeArray.length > 0 || excludeArray.length > 0) {
        enumObject = filterEnum({
            objSource,
            includeArray,
            excludeArray
        })
    }

    let listResult = []
    for (var k in enumObject) {
        let item = {}
        item[key] = parseEnumKey(k)
        item[value] = enumObject[k]

        listResult.push(item)
    }

    return listResult
}

// start表单验证规则解析

const createRules = function ({
    rule,
    finallResult
}) {
    /// <summary>生成表单验证规则</summary>
    /// <param name=".rule">传入的限定规则条件</param>
    /// <param name=".finallResult">可选，默认为true，是生成最终规则（多级规则可用）</param> 
    finallResult = Object.prototype.toString.call(finallResult) == '[object Boolean]' ? finallResult : true

    if (Object.prototype.toString.call(rule) == '[object String]') {
        let result = {}

        if (rule.toLowerCase() == 'required') {
            result = {
                required: true,
                trigger: ['blur', 'change']
            }
        } else {
            if (validator[rule]) {
                result = {
                    validator: validator[rule],
                    trigger: ['blur', 'change']
                }
            }
        }

        return finallResult ? [result] : result
    } else if (Object.prototype.toString.call(rule) == '[object Array]') {
        let result = []

        rule.forEach(r => {
            result.push(createRules({
                rule: r,
                finallResult: false
            }))
        })

        return result
    } else if (Object.prototype.toString.call(rule) == '[object Object]') {
        return rule
    }

    return null
}

const fillItemRule = function ({
    itemRule
}) {
    let result

    // 属性值类型为对象时
    if (Object.prototype.toString.call(itemRule) == '[object Object]') {
        // 不存在rules属性
        if (!itemRule.hasOwnProperty('rules')) {
            throw new Error(`the prototype '${key}' of form rules miss 'rules' prototype`)
        }
        // rules属性值类型不为数组
        if (Object.prototype.toString.call(itemRule.rules) != '[object Array]') {
            throw new Error(`the prototype '${key}' of form rules's "rules" must be an array type.`)
        }

        let keyword = itemRule.keyword || ''
        let inputType = itemRule.inputType || 'input'

        itemRule.rules.forEach(rule => {
            if (!rule.hasOwnProperty('message')) {
                let message = '',
                    type = rule.hasOwnProperty('type') || '',
                    hasRequired = rule.hasOwnProperty('required')

                if (hasRequired) {
                    message = requiredMsg
                } else if (type == 'number') {
                    message = numberMsg
                }

                rule.message = message
            }
        })

        result = itemRule.rules
    }
    // 属性值为数组时
    else if (Object.prototype.toString.call(itemRule) == '[object Array]') {
        itemRule.forEach(rule => {
            if (!rule.hasOwnProperty('message')) {
                let message = '',
                    type = rule.hasOwnProperty('type') || '',
                    hasRequired = rule.hasOwnProperty('required')

                if (hasRequired) {
                    message = requiredMsg
                } else if (type == 'number') {
                    message = numberMsg
                }

                rule.message = message
            }
        })

        result = itemRule
    }

    return result
}

const convertRules = function ({
    propRules,
    form,
    itemRule
}) {
    /// <summary>转换验证规则，自动填充message</summary>
    /// <param name=".propRules">可选，传入已有的规则对象</param>
    /// <param name=".form">可选，传入form表单元素配置对象</param>

    let result = {}

    if (propRules || form) {
        let rules = propRules || {}

        // 如果是配置，则取配置列表里的rule
        if (Object.prototype.toString.call(form) === '[object Object]') {
            // 多个表单groups
            if (form.groups) {
                form.groups.forEach(group => {
                    Object.keys(group.column).forEach(prop => {
                        let column = group.column[prop]
                        if (column.disabled) { return }
                        let r = createRules({
                            rule: column.rules
                        })

                        if (r != null) {
                            rules[prop] = r
                        }
                    })
                })
            } else {
                Object.keys(form.columns).forEach(prop => {
                    let ent = form.columns[prop]
                    if (ent.disabled) { return }

                    let r = createRules({
                        rule: ent.rules
                    })

                    if (r != null) {
                        rules[prop] = r
                    }
                })
            }
        }

        Object.keys(rules).forEach(key => {
            let itemRule = rules[key]

            if (Object.prototype.toString.call(itemRule) === '[object String]') {
                itemRule = createRules({
                    rule: itemRule
                })
            }

            result[key] = fillItemRule({
                itemRule
            })
        })
    } else if (itemRule) {
        itemRule = createRules({
            rule: itemRule
        })

        result = fillItemRule({
            itemRule
        })
    } else {
        result = null
    }

    // console.groupEnd();
    // console.group('rules result', result);
    // console.groupEnd();

    return result
}

// 创建表单验证规则
const formRules = function (form) {
    let rules = {}

    if (this.rules != null) {
        rules = convertRules({
            propRules: this.rules
        })
    } else {
        if (form) {
            rules = convertRules({
                form: form
            })
        } else {
            rules = convertRules({
                propRules: this.rules
            })
        }
    }

    return rules
}

//生成UUID
const CreateUuid = function (len, radix) {
    var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
    var uuid = [], i;
    radix = radix || chars.length;
    if (len) {
        for (i = 0; i < len; i++) uuid[i] = chars[0 | Math.random() * radix];
    } else {
        var r;
        uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
        uuid[14] = '4';
        for (i = 0; i < 36; i++) {
            if (!uuid[i]) {
                r = 0 | Math.random() * 16;
                uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];
            }
        }
    }
    return uuid.join('');
}

// end 解析表单验证结束

const Guid = function () {
    function S4() {
        return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1)
    }
    return (S4() + S4() + '-' + S4() + '-' + S4() + '-' + S4() + '-' + S4() + S4() + S4())
}

// 查询条件解码对象
const CreateConditionObj = function (searchInfo) {
    let condition = {}
    Object.keys(searchInfo).forEach((event) => {
        let info = searchInfo[event]
        if (info.value) {
            condition[event] = info.value;
        }
    })

    // 返回拼接查询条件
    return condition
}
// 查询条件解码对象(通用)
const CreateConditionJson = function (searchInfo, pageData) {
    let condition = " 1=1 "
    let params = {}
    Object.keys(searchInfo).forEach((event) => {
        let info = searchInfo[event]
        let where = info.where || '=';

        condition += ` and ${event} ${where} @${event}`
        if (where == 'like') {
            params[event] = '%' + info.value + '%';
        } else {
            condition[event] = info.value;
        }
    })
    let json = { Condition: condition, Params: params };
    if (pageData) {
        json = {
            Condition: condition,
            Params: params,
            CurrentPage: pageData.CurrentPage,
            PageSize: pageData.PageSize,
        }
    }
    // 返回拼接查询条件
    return json
}


// 查询条件解码对象
const CreateConditionArry = function (searchInfo) {
    let conditions = []
    Object.keys(searchInfo).forEach((event) => {
        let info = searchInfo[event]
        let displayType = "";

        //检索查询类型
        if (info.displayType) {
            displayType = info.displayType;
        } else {
            switch (info.componentName) {
                case "form-input":
                    displayType = "like"
                    break;
                case "form-select":
                    displayType = "Equal"
                    break
                case "form-checkbox":
                    displayType = "Contains"
                    break
                case "form-form-datePicker":
                    if (info.value.length > 1) {
                        conditions.push({
                            name: event,
                            value: info.value[0],
                            displayType: "ThanOrEqual"
                        })
                        conditions.push({
                            name: event,
                            value: info.value[1],
                            displayType: "LessOrequal"
                        })
                        break
                    }
                    break
                default:
                    break
            }
        }

        //查询对象组装
        if (info.value) {
            let condition = {
                name: event,
                value: info.value,
                displayType: displayType
            }
            conditions.push(condition)
        }
    })

    // 返回拼接查询条件
    return conditions
}
// 创建查询条件
const CreateCondition = function (searchInfo) {
    let condition = ''
    Object.keys(searchInfo).forEach((event) => {
        let info = searchInfo[event]

        // 检验是否有值
        if (info.value) {
            let and = condition ? ' and ' : ''
            let where = ''

            // 下拉框条件匹配
            if (info.componentName === 'form-select') {
                where = ' ' + event + `='${info.value}'`
            } else if (info.componentName === 'form-datePicker') { // 时间选择
                if (info.value.length > 1) {
                    where = ` '${info.value[0]}'<=` + event
                    where += ` and ${event}<='${info.value[1]}'`
                } else {
                    where = ' ' + event + ` like '${info.value}%'`
                }
            } else { // 文本框
                where = ' ' + event + ` like '%${info.value}%'`
            }

            if (where) {
                condition += and + where
            }
        }
    })

    // 返回拼接查询条件
    return condition
}


// 剥离上传文件返回后得上传字符串
const uploadStr = function (data) {
    let str = ''
    if (data) {
        data.forEach((ent) => {
            if (ent.status != "success") {
                return;
            }
            str += ((str ? "," : "") + ent.value);
        });
    }
    // 返回拼接
    return str
}

// 分页配置
function PageData() {
    this.CurrentPage = 1
    this.PageSize = 10
    this.TotalCount = 0
    this.TotalPage = 1
    this.PageSizeSource = [10, 20, 30, 40, 50, 100]
}

const core = {
    Class: {
        PageData
    },
    Enum,
    convertEnum,
    clone,
    convertOptions,
    convertRules,
    formRules,
    Guid,
    CreateCondition,
    CreateConditionObj,
    CreateConditionJson,
    CreateConditionArry,
    uploadStr,
    CreateUuid
}

export default core